package com.dlc.shop.service.impl;


import com.dlc.shop.common.bean.leaf.LeafAlloc;
import com.dlc.shop.dao.IDAllocMapper;
import com.dlc.shop.service.IDAllocDao;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import javax.sql.DataSource;
import java.util.List;

/**
 * @author leaf
 */
public class IDAllocDaoImpl implements IDAllocDao {

    final SqlSessionFactory sqlSessionFactory;

    public IDAllocDaoImpl(DataSource dataSource) {
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment("development", transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.addMapper(IDAllocMapper.class);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
    }

    @Override
    public List<LeafAlloc> getAllLeafAllocs() {
        try (SqlSession sqlSession = sqlSessionFactory.openSession(false)) {
            return sqlSession.selectList("com.dlc.shop.dao.IDAllocMapper.getAllLeafAllocs");
        }
    }

    @Override
    public LeafAlloc updateMaxIdAndGetLeafAlloc(String tag, int length) {
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            // 先开启事务执行更新操作，这个时候就会有数据库的行锁，不需要其他分布式锁相关中间件处理
            sqlSession.update("com.dlc.shop.dao.IDAllocMapper.updateMaxId", tag);
            LeafAlloc result = sqlSession.selectOne("com.dlc.shop.dao.IDAllocMapper.getLeafAlloc", tag);
            // 长度过长，要重新初始化成step
            if (String.valueOf(result.getMaxId()).length() > length) {
                sqlSession.update("com.dlc.shop.dao.IDAllocMapper.updateMaxIdToStep", tag);
                result.setMaxId(result.getStep());
            }
            // 提交事务，释放锁
            sqlSession.commit();
            return result;
        }
    }

    @Override
    public LeafAlloc updateMaxIdByCustomStepAndGetLeafAlloc(LeafAlloc leafAlloc, int length) {
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            // 先开启事务执行更新操作，这个时候就会有数据库的行锁，不需要其他分布式锁相关中间件处理
            sqlSession.update("com.dlc.shop.dao.IDAllocMapper.updateMaxIdByCustomStep", leafAlloc);
            LeafAlloc result = sqlSession.selectOne("com.dlc.shop.dao.IDAllocMapper.getLeafAlloc",
                    leafAlloc.getBizTag());
            // 长度过长，要重新初始化成step
            if (String.valueOf(result.getMaxId()).length() > length) {
                // 如果超过最大值，就按最大值的id来返回即可
                long maxValue = Math.round(Math.pow(10, length)) - 1;
                result.setValue(result.getMaxId() - leafAlloc.getStep());
                result.setMaxId(maxValue);
                // 初始化id的获取数量
                leafAlloc.setStep(result.getStep());
                // 初始化表中的id数据
                sqlSession.update("com.dlc.shop.dao.IDAllocMapper.updateMaxIdToStep", leafAlloc.getBizTag());
            }
            // 提交事务，释放锁
            sqlSession.commit();
            return result;
        }
    }

    @Override
    public List<String> getAllTags() {
        try (SqlSession sqlSession = sqlSessionFactory.openSession(false)) {
            return sqlSession.selectList("com.dlc.shop.dao.IDAllocMapper.getAllTags");
        }
    }

}
